/*
 * Copyright 2012-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot;

import java.util.function.Supplier;

import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;

/**
 * 一个简单的引导上下文，在启动期间和 {@link Environment} 后处理阶段可用，
 * 直到 {@link ApplicationContext} 准备完成为止。
 * <p>
 * 提供对单例的延迟访问，这些单例可能创建成本较高，或需要在
 * {@link ApplicationContext} 可用之前共享。
 *
 * @author Phillip Webb
 * @since 2.4.0
 */
public interface BootstrapContext {

	/**
	 * 如果类型已注册，则从上下文中返回一个实例。如果之前没有访问过，
	 * 将会创建该实例。
	 *
	 * @param <T> 实例类型
	 * @param type 实例类型
	 * @return 由上下文管理的实例
	 * @throws IllegalStateException 如果类型尚未注册
	 */
	<T> T get(Class<T> type) throws IllegalStateException;

	/**
	 * 如果类型已注册，则从上下文中返回一个实例。如果之前没有访问过，
	 * 将会创建该实例。
	 *
	 * @param <T> 实例类型
	 * @param type 实例类型
	 * @param other 如果类型尚未注册时使用的实例
	 * @return 实例
	 */
	<T> T getOrElse(Class<T> type, T other);

	/**
	 * 如果上下文中已经注册了指定类型，则返回其实例。如果之前未访问过该类型，则会创建实例。
	 *
	 * @param <T> 实例的类型
	 * @param type 要获取的实例类型
	 * @param other 如果该类型尚未注册，则使用此提供者来供应一个实例
	 * @return 上下文中的实例
	 */
	<T> T getOrElseSupply(Class<T> type, Supplier<T> other);

	/**
	 * 如果上下文中已经注册了指定类型，则返回其实例。如果之前未访问过该类型，则会创建实例。
	 *
	 * @param <T> 实例的类型
	 * @param <X> 如果该类型未注册时要抛出的异常类型
	 * @param type 要获取的实例类型
	 * @param exceptionSupplier 当类型未注册时，用于提供要抛出的异常
	 * @return 由上下文管理的实例
	 * @throws X 如果该类型未注册
	 * @throws IllegalStateException 如果该类型未注册（可能由异常供应器抛出）
	 */
	<T, X extends Throwable> T getOrElseThrow(Class<T> type, Supplier<? extends X> exceptionSupplier) throws X;

	/**
	 * 判断给定类型是否已经在上下文中注册。
	 *
	 * @param <T> 实例的类型
	 * @param type 要检查的实例类型
	 * @return 如果该类型已注册则返回 {@code true}
	 */
	<T> boolean isRegistered(Class<T> type);

}
